package com.spic.business.blast.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.spic.business.alarm.domain.DeviceInfoVo;
import com.spic.business.alarm.domain.EmpLocation;
import com.spic.business.alarm.mapper.EmpLocationMapper;
import com.spic.business.alarm.mapper.WeatherDataMapper;
import com.spic.business.alarm.service.DeviceService;
import com.spic.business.blast.domain.*;
import com.spic.business.blast.domain.vo.BlastAlarmVo;
import com.spic.business.blast.domain.vo.BlastAreaVo;
import com.spic.business.blast.domain.vo.BlastPoint;
import com.spic.business.blast.domain.vo.PresetVo;
import com.spic.business.blast.mapper.BlastDeploymentMapper;
import com.spic.business.blast.service.IBlastAlarmService;
import com.spic.business.blast.service.IBlastDeploymentService;
import com.spic.business.bp.domain.BpAlarmVo;
import com.spic.business.bp.domain.BpPoint;
import com.spic.business.common.core.eum.BlastState;
import com.spic.business.common.core.utils.DateUtil;
import com.spic.business.datamanagement.blast.domain.BlastDeploymentDirty;
import com.spic.business.datamanagement.blast.mapper.BlastDeploymentDirtyMapper;
import com.spic.business.getui.service.PushService;
import com.spic.business.hik.constant.HkConstant;
import com.spic.business.preset_point.domain.PresetsPosition;
import com.spic.business.preset_point.mapper.PresetsPositionMapper;
import com.spic.business.preset_point.service.IPresetsPositionService;
import com.spic.common.core.constant.SecurityConstants;
import com.spic.common.core.domain.R;
import com.spic.common.core.text.UUID;
import com.spic.common.core.utils.DateUtils;
import com.spic.common.core.utils.SecurityUtils;
import com.spic.common.core.utils.StringUtils;
import com.spic.common.core.utils.bean.BeanUtils;
import com.spic.system.api.RemoteNoticeInfoService;
import com.spic.system.api.RemoteUserService;
import com.spic.system.api.domain.SysNoticeInfo;
import com.spic.system.api.domain.SysRole;
import com.spic.system.api.domain.SysUser;
import com.spic.system.api.model.LoginUser;
import com.vividsolutions.jts.algorithm.ConvexHull;
import com.vividsolutions.jts.geom.*;
import com.vividsolutions.jts.operation.buffer.BufferOp;
import org.apache.commons.math3.util.Pair;
import org.geotools.geometry.jts.JTS;
import org.geotools.geometry.jts.JTSFactoryFinder;
import org.geotools.referencing.CRS;
import org.opengis.referencing.FactoryException;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.operation.MathTransform;
import org.opengis.referencing.operation.TransformException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * 爆破布防Service业务层处理
 *
 * @author spic
 * @date 2022-03-03
 */
@Service
public class BlastDeploymentServiceImpl implements IBlastDeploymentService
{
    @Autowired
    private BlastDeploymentMapper blastDeploymentMapper;
    @Autowired
    private RemoteUserService remoteUserService;
    @Autowired
    private PresetsPositionMapper presetsPositionMapper;

    @Autowired
    private EmpLocationMapper empLocationMapper;

    @Autowired
    private IPresetsPositionService IPresetsPositionService;

    @Autowired
    private DeviceService deviceService;

    @Autowired
    private IBlastAlarmService blastAlarmService;

    @Autowired
    private ThreadPoolExecutor executor;

    @Autowired
    private WeatherDataMapper weatherDataMapper;

    @Autowired
    private RemoteNoticeInfoService remoteNoticeInfoService;

    @Autowired
    private PushService doPush;

    @Autowired
    private BlastDeploymentDirtyMapper blastDeploymentDirtyMapper;

    private static final Logger log = LoggerFactory.getLogger(BlastDeploymentServiceImpl.class);
    /**
     * 查询爆破布防
     *
     * @param id 爆破布防主键
     * @return 爆破布防
     */
    @Override
    public BlastDeployment selectBlastDeploymentById(String id)
    {

        return blastDeploymentMapper.selectBlastDeploymentById(id);
    }

    /**
     * 查询爆破布防列表
     *
     * @param blastDeployment 爆破布防
     * @return 爆破布防
     */
    @Override
    public List<BlastDeployment> selectBlastDeploymentList(BlastDeployment blastDeployment)
    {
        R<SysUser> userData = remoteUserService.getUserById(SecurityUtils.getUserId());
        SysUser user = userData.getData();
        List<SysRole> roles = user.getRoles();
        //监察人员
        List<SysRole> jiancharenyuanList = roles.stream().filter(r -> r.getRoleKey().equals("jiancharenyuan")).collect(Collectors.toList());
        //穿爆技术人员
        List<SysRole> chuanbaojsryList = roles.stream().filter(r -> r.getRoleKey().equals("chuanbaojsry")).collect(Collectors.toList());

        List<BlastDeployment> blastDeploymentList = blastDeploymentMapper.selectBlastDeploymentList(blastDeployment);

        Iterator<BlastDeployment> it = blastDeploymentList.iterator();
        while (it.hasNext()) {
            BlastDeployment b = it.next();
            if (StringUtils.isNull(b.getUpdateTime())) {
                if(jiancharenyuanList!=null&& jiancharenyuanList.size()>0)
                {
                    b.setIsUpdate(false);
                }
            }else{ //不可修改
                if(jiancharenyuanList!=null&& jiancharenyuanList.size()>0)
                {
                    b.setIsUpdate(true);
                }else{
                    b.setIsUpdate(false);
                }
            }
        }
        return blastDeploymentList;
    }


    @Override
    public List<BlastDeployment> selectBlastDeploymentListByDate(String date)
    {
        BlastDeployment blastDeployment = new BlastDeployment();
        String yyyyMMdd ="";
        if(StringUtils.isNull(date)){
            yyyyMMdd = DateUtil.fmtDateToStr(new Date(), "yyyyMMdd");
        }else{
            yyyyMMdd =  date;
        }
        blastDeployment.setCode(yyyyMMdd);

        return blastDeploymentMapper.selectBlastDeploymentListByCode(blastDeployment);
    }

    @Override
    public PresetVo getPreset(String taskId)
    {
        //将爆区的中心点和各个经纬度进行对比，选取最近的经纬度对应的预置点
        GeometryFactory geometryFactory = JTSFactoryFinder.getGeometryFactory();
        BlastDeployment blastDeployment = blastDeploymentMapper.selectBlastDeploymentById(taskId);
        String cameraIndex = blastDeployment.getCameraIndexCodeType();
        //获取摄像头的预置点的经纬度等信息
        PresetsPosition presetsPosition = new PresetsPosition();
        presetsPosition.setParentId(cameraIndex);
        List<PresetsPosition> presetList = IPresetsPositionService.selectPresetsPositionList(presetsPosition);
        List<PresetsPosition> presets = presetList.stream().filter(item -> !"0".equals(item.getParentId())).collect(Collectors.toList());

        String position = blastDeployment.getChargePosition();
        JSONArray pos = JSONArray.parseArray(position);
        Coordinate[] c = new Coordinate[pos.size()];
        for (int j = 0; j < pos.size(); j++)
        {
            JSONObject point = pos.getJSONObject(j);
            double lon = point.getDouble("longitude");
            double lat = point.getDouble("latitude");
            c[j] = new Coordinate(lon, lat);
        }
        ConvexHull ch = new ConvexHull(c, geometryFactory);
        Coordinate[] hull  = ch.getConvexHull().getCoordinates();
        Polygon pplygon = geometryFactory.createPolygon(hull);
        Point interiorPoint = pplygon.getInteriorPoint();
        //获取和质心点最近的坐标
        List<Pair<String, Double>> distList = new ArrayList<>();
        for (int i = 0; i < presets.size(); i++)
        {
            PresetsPosition postion = presets.get(i);
            Point point =geometryFactory.createPoint(new Coordinate(Double.valueOf(postion.getLongitude()),Double.valueOf(postion.getLatitude())));
            Pair<String, Double> pair = new Pair(postion.getPresetPointindex(),interiorPoint.distance(point));
            distList.add(pair);
        }
        Optional<Pair<String, Double>> minDist = distList.stream().sorted(Comparator.comparing(t ->t.getValue())).findFirst();
        PresetVo presetVo = new PresetVo();
        presetVo.setCameraIndexCode(cameraIndex);
        presetVo.setPresetIndex(minDist.get().getKey());
        return presetVo;
    }

    @Override
    public void calcAlarm()
    {
        List<BlastAreaVo> polygons = getPolygons();
        //获取车辆定位信息
        List<DeviceInfoVo> allDeviceInfoVo = deviceService.getAllDeviceInfoVo();

        GeometryFactory geometryFactory = JTSFactoryFinder.getGeometryFactory();

        //获取人员位置信息，人员定位系统
        String today = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) + "%";
        List<EmpLocation> locationInfo = empLocationMapper.getLocationInfo(today);

        for (int i = 0; i < polygons.size(); i++)
        {

            BlastAreaVo entry = polygons.get(i);
            String taskId = entry.getTaskId();
            String taskName = entry.getTaskName();
            List<BlastPoint> points = entry.getArea();
            List<Coordinate> collect = points.stream().map(item ->
                 new Coordinate(item.getLon(), item.getLat())
            ).collect(Collectors.toList());
            Coordinate[] coordinates = new Coordinate[collect.size()];
            Polygon polygon = geometryFactory.createPolygon(collect.toArray(coordinates));
            List<DeviceInfoVo> deviceAlarms = new ArrayList<>();
            List<EmpLocation> personAlarms = new ArrayList<>();
            for (int j = 0; j < allDeviceInfoVo.size(); j++)
            {
                DeviceInfoVo item = allDeviceInfoVo.get(j);
                if(item.getLongitude()!=null && item.getLatitude()!=null){
                    Point p = geometryFactory.createPoint(new Coordinate(item.getLongitude(), item.getLatitude()));
                    BlastAlarmVo blastAlarm = new BlastAlarmVo();
                    BlastAlarm ba = new BlastAlarm();
                    ba.setBlastTaskId(taskId);
                    ba.setAlarmObj(item.getDeviceName());
                    blastAlarm.setBlastTaskId(taskId);
                    blastAlarm.setAlarmObj(item.getDeviceName());
                    //是否告警
                    if (polygon.contains(p))
                    {
                        Date date = new Date();
                        deviceAlarms.add(item);
                        //查询是否有告警，有则更新，无则加
                        BlastAlarm b = blastAlarmService.selectBlastAlarmByAlarm(ba);
                        blastAlarm.setBlastTaskName(taskName);
                        blastAlarm.setAlarmTime(new Date());
                        blastAlarm.setObjType("1");
                        blastAlarm.setAlarmType("0");
                        if(b == null)
                        {
                            blastAlarmService.insertBlastAlarm(blastAlarm);
                        }
                        else
                        {
                            blastAlarmService.updateBlastAlarm(blastAlarm);
                        }

                        //插入告警信息 个推和 pc消息
                        executor.execute(() -> {
                            //通过deviceName获取userId
                            String userId = this.getUserIdByDeviceName(item.getDeviceName());
                            //插入业务告警主表
                            //插入业务告警子表
                            if(StringUtils.isNotEmpty(userId)){
                                //推送消息提醒
                                this.noticeInfo(item.getDeviceName(), taskName, userId, date);
                            }
                        });
                    }
                    else
                    {
                        BlastAlarm b = blastAlarmService.selectBlastAlarmByAlarm(ba);
                        if (b != null)
                        {
                            blastAlarm.setAlarmType("1");
                            blastAlarmService.updateBlastAlarm(blastAlarm);
                        }
                    }
                }
            }

            for (int k = 0; k < locationInfo.size(); k++)
            {
                EmpLocation e = locationInfo.get(k);
                Point p =  geometryFactory.createPoint(new Coordinate(Double.valueOf(e.getLon()), Double.valueOf(e.getLat())));
                BlastAlarmVo blastAlarm = new BlastAlarmVo();
                BlastAlarm ba = new BlastAlarm();
                ba.setBlastTaskId(taskId);
                ba.setAlarmObj(e.getCardNo()); //@TODO
                blastAlarm.setBlastTaskId(taskId);
                blastAlarm.setAlarmObj(e.getCardNo()); //@TODO
                if (polygon.contains(p))
                {
                    personAlarms.add(e);
                    blastAlarm.setBlastTaskName(taskName);
                    blastAlarm.setAlarmTime(new Date());
                    blastAlarm.setObjType("0");
                    blastAlarm.setAlarmType("0");
                    //查询是否有告警，有则更新，无则加
                    BlastAlarm b = blastAlarmService.selectBlastAlarmByAlarm(ba);
                    if(b == null)
                    {
                        blastAlarmService.insertBlastAlarm(blastAlarm);
                    }
                    else
                    {
                        blastAlarmService.updateBlastAlarm(blastAlarm);
                    }
                }
                else
                {
                    BlastAlarm b = blastAlarmService.selectBlastAlarmByAlarm(ba);
                    if (b != null)
                    {
                        blastAlarm.setAlarmType("1");
                        blastAlarmService.updateBlastAlarm(blastAlarm);
                    }
                }
            }
        }
    }
    /**
     * 通过设备名称获取userId
     * @param deviceName 设备名称
     * @return userId
     */
    public String getUserIdByDeviceName(String deviceName){
        int account = weatherDataMapper.selectAccountByDeviceName(deviceName);
        if(account!=0){
            String userName =  String.format("%08d", account);
            R<LoginUser> loginUser = remoteUserService.getUserInfo(userName, SecurityConstants.INNER);
            if(loginUser!=null && loginUser.getData().getSysUser().getUserId()!=null){
                return loginUser.getData().getSysUser().getUserId().toString();
            }
        }
        return "";
    }

    /**
     * 推送消息
     */
    public void noticeInfo(String deviceName,String taskName, String userId, Date date){
        SysNoticeInfo info = new SysNoticeInfo();
        info.setContent("设备名称: "+deviceName+",已进入爆区警戒范围。报警时间："+
                DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
        info.setTitle("爆破布防告警");
        info.setUserId(userId);
        info.setCreateBy(userId);
        info.setCreateTime(date);
        remoteNoticeInfoService.add(info);
        String cid = remoteUserService.getUserById(new Long(userId)).getData().getCid();
        Integer clientType = remoteUserService.getUserById(new Long(userId)).getData().getClientType();
        if(StringUtils.isNotEmpty(cid)){
            doPush.push(cid, "爆破布防告警","设备名称: "+deviceName+",已进入" + taskName + "警戒范围。报警时间："+
                    DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date),clientType);
        }
    }

    @Override
    public List<BlastAreaVo> getPolygons()
    {
        String mineScope = "[{\"longitude\":\"119.594174\",\"latitude\":\"45.453679\"},\n" +
                "{\"longitude\":\"119.607074\", \"latitude\":\"45.478440\"}, \n" +
                "{\"longitude\":\"119.610371\", \"latitude\":\"45.478382\"}, \n" +
                "{\"longitude\":\"119.616403\", \"latitude\":\"45.482770\"}, \n" +
                "{\"longitude\":\"119.607683\", \"latitude\":\"45.487019\"}, \n" +
                "{\"longitude\":\"119.618261\", \"latitude\":\"45.500060\"}, \n" +
                "{\"longitude\":\"119.617803\", \"latitude\":\"45.501796\"},\n" +
                "{\"longitude\":\"119.582003\", \"latitude\":\"45.520473\"}, \n" +
                "{\"longitude\":\"119.563157\", \"latitude\":\"45.513818\"}, \n" +
                "{\"longitude\":\"119.560511\", \"latitude\":\"45.498954\"}, \n" +
                "{\"longitude\":\"119.572788\", \"latitude\":\"45.482878\"}, \n" +
                "{\"longitude\":\"119.571973\", \"latitude\":\"45.477236\"},\n" +
                "{\"longitude\":\"119.566309\", \"latitude\":\"45.465388\"}, \n" +
                "{\"longitude\":\"119.570645\", \"latitude\":\"45.461327\"},\n" +
                "{\"longitude\":\"119.594174\", \"latitude\":\"45.453679\"}\n" +
                "]";
        Polygon mineScopePolygons = getPolygons(mineScope);

        final String  stats = "4";
        BlastDeployment blastDeployment = new BlastDeployment();
        blastDeployment.setState(stats);
        List<BlastDeployment> tasks = blastDeploymentMapper.selectBlastDeploymentList(blastDeployment);

        BlastDeployment blastDeployment2 = new BlastDeployment();
        blastDeployment2.setState("5");
        List<BlastDeployment> tasks2 = blastDeploymentMapper.selectBlastDeploymentList(blastDeployment2);
        tasks.addAll(tasks2);
        GeometryFactory geometryFactory = JTSFactoryFinder.getGeometryFactory();
        List<BlastAreaVo> list = new ArrayList<>();
        try
        {
            if (tasks != null && tasks.size() > 0)
            {
                for (int i = 0; i < tasks.size(); i++)
                {
                    BlastAreaVo polygonMap = new BlastAreaVo();
                    List<BlastPoint> points = new ArrayList<>();
                    BlastDeployment blast = tasks.get(i);
                    String taskId = blast.getId();
                    String taskName = blast.getTaskName();
                    String holeStr = blast.getChargePosition();
                    String waikuoMeter = blast.getHolePositionType();
                    String taskCode = blast.getCode();
                    String yaoliang = blast.getTotalExplosiveDosage() == null ? "" : blast.getTotalExplosiveDosage().toString();
                    DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
                    String taskBegin = df.format(blast.getBeginTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime());
                    String taskEnd = df.format(blast.getEndTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime());

                    JSONArray array = JSONArray.parseArray(holeStr);
                    //排除不在矿区内的点
                    Iterator<Object> iterator = array.iterator();
                    while (iterator.hasNext()) {
                        JSONObject next = (JSONObject)iterator.next();
                        Point p = geometryFactory.createPoint(new Coordinate(next.getDouble("longitude"), next.getDouble("latitude")));
                        if (! mineScopePolygons.contains(p)) {
                            iterator.remove();
                        }
                    }
                    //防止报错:Invalid number of points in LineString (found 1 - must be 0 or >= 2)
                    if(array.size() < 2) {
                        continue;
                    }
                    Coordinate[] c = new Coordinate[array.size()];
                    for (int j = 0; j < array.size(); j++)
                    {
                        JSONObject point = array.getJSONObject(j);
                        double lon = point.getDouble("longitude");
                        double lat = point.getDouble("latitude");
                        c[j] = new Coordinate(lon, lat);
                    }
                    //求解凸包
                    ConvexHull ch = new ConvexHull(c, geometryFactory);
                    Coordinate[] hull  = ch.getConvexHull().getCoordinates();
                    Polygon plygon = geometryFactory.createPolygon(hull);
                    Point center = plygon.getInteriorPoint();
                    //外扩多少米
                    Geometry waikuo = getBufferedZipPolygon(plygon, Integer.valueOf(waikuoMeter));
                    //获得外扩的米数
                    Coordinate[] waiPolygon = waikuo.getCoordinates();
                    points = Arrays.stream(waiPolygon).map(item -> new BlastPoint(item.x, item.y)).collect(Collectors.toList());
                    polygonMap.setArea(points);
                    polygonMap.setTaskId(taskId);
                    polygonMap.setTaskName(taskName);
                    polygonMap.setCode(taskCode);
                    polygonMap.setBeginTime(taskBegin);
                    polygonMap.setEndTime(taskEnd);
                    polygonMap.setWaikuo(waikuoMeter);
                    polygonMap.setCenterLon(center.getX());
                    polygonMap.setCenterLat(center.getY());
                    polygonMap.setYaoliang(yaoliang);
                    polygonMap.setPointInfo(holeStr);
                    list.add(polygonMap);
                }
            }
        }
        catch (FactoryException e)
        {
            e.printStackTrace();
        }
        catch (TransformException e)
        {
            e.printStackTrace();
        }

        return list;
    }

    /**
     * WGS84 转 墨卡托    119.2344，,45.3344   ----->  87646547.33   89344555.33 从经纬度转换成米
     * @param geometry
     * @return
     */
    private Geometry convertWGS84toMercator(Geometry geometry)
    {
        CoordinateReferenceSystem wgsCRS;
        CoordinateReferenceSystem distanceMetersCRS;
        try {
            wgsCRS = CRS.decode("EPSG:4326", true);
            distanceMetersCRS = CRS.decode("EPSG:3857", true);
            MathTransform transform = CRS.findMathTransform(wgsCRS, distanceMetersCRS);
            Geometry transformed = JTS.transform(geometry, transform);
            return transformed;
        } catch (FactoryException e) {
            e.printStackTrace();
        } catch (TransformException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 布防范围外扩多少米
     * @param zipPolygon  原始多边形
     * @param distanceMeters  外扩距离 米
     * @return 外扩后的多边行
     * @throws FactoryException
     * @throws TransformException
     */
    private Geometry getBufferedZipPolygon(Polygon zipPolygon, double distanceMeters) throws FactoryException, TransformException
    {
        CoordinateReferenceSystem wgsCRS;
        CoordinateReferenceSystem distanceMetersCRS;
        try {
            wgsCRS = CRS.decode("EPSG:4326", true);
            distanceMetersCRS = CRS.decode("EPSG:3857", true);

            MathTransform transform = CRS.findMathTransform(wgsCRS, distanceMetersCRS);
            MathTransform reverseTransform = CRS.findMathTransform(distanceMetersCRS, wgsCRS);

            Geometry transformedZipPolygon = JTS.transform(zipPolygon, transform);
            //不可设置样式的
//            Geometry bufferZipPolygon = transformedZipPolygon.buffer(distanceMeters);

            //可设置样式的
            BufferOp bufOp = new BufferOp(transformedZipPolygon);
            bufOp.setEndCapStyle(BufferOp.CAP_SQUARE);
            Geometry bufferZipPolygon = bufOp.getResultGeometry(distanceMeters);

            return JTS.transform(bufferZipPolygon, reverseTransform);
        } catch (FactoryException e) {
            e.printStackTrace();
        } catch (TransformException e) {
            e.printStackTrace();
        }

        return null;
    }

    /**
     * 新增爆破布防
     *
     * @param blastDeployment 爆破布防
     * @return 结果
     */
    @Transactional
    @Override
    public int insertBlastDeployment(BlastDeployment blastDeployment)
    {
        //编码是否存在
        String code = blastDeployment.getCode();
        BlastDeployment blastDeploymentBycode = blastDeploymentMapper.selectBlastDeploymentByCode(code);
        if(StringUtils.isNotNull(blastDeploymentBycode)){
            return 0;
        }

        String uuid = UUID.randomUUID().toString().replaceAll("-", "");
        blastDeployment.setCreateTime(DateUtils.getNowDate());
        blastDeployment.setId(uuid);
        blastDeployment.setState(BlastState.CHARGE.getCode());
        int rows = blastDeploymentMapper.insertBlastDeployment(blastDeployment);
        insertBlastDeploymentHoleSubtable(blastDeployment);
        return rows;
    }

    /**
     * 修改爆破布防
     *
     * @param blastDeployment 爆破布防
     * @return 结果
     */
    @Transactional
    @Override
    public int updateBlastDeployment(BlastDeployment blastDeployment)
    {
        String chargePosition = blastDeployment.getChargePosition();
        String id = blastDeployment.getId();
        BlastDeployment blast = blastDeploymentMapper.selectBlastDeploymentById(id);

        if(StringUtils.isNotNull(blast.getChargePosition()) && !"[]".equals(blast.getChargePosition())){
            if(StringUtils.isNotNull(chargePosition) ){
                List<ChargePositionVo> cList = JSON.parseArray(blast.getChargePosition(), ChargePositionVo.class);
                ChargePositionVo chargePositionVo = JSON.parseObject(chargePosition, ChargePositionVo.class);
                String uuid = UUID.randomUUID().toString().replaceAll("-", "");
                chargePositionVo.setChargeHoleId(uuid);
                cList.add(chargePositionVo);
                String s = JSONArray.parseArray(JSON.toJSONString(cList)).toString();
                blastDeployment.setChargePosition(s);
            }
        }else{
            if(StringUtils.isNotNull(chargePosition)){
                ChargePositionVo chargePositionVo = JSON.parseObject(chargePosition, ChargePositionVo.class);
                String uuid = UUID.randomUUID().toString().replaceAll("-", "");
                chargePositionVo.setChargeHoleId(uuid);
                String s = JSON.toJSONString(chargePositionVo);
                String news = "["+s+"]";
                blastDeployment.setChargePosition(news);
            }
        }
        //设置 开始布防 和 撤销布防时间 确认时间 确认人 爆破时间
        if(StringUtils.isNotNull(blastDeployment.getState())){
            if(BlastState.CANCEL_DEPLOYMENT.getCode().equals(blastDeployment.getState())){  //撤销布防 更新 引爆时间
                blastDeployment.setDetonationTime(new Date());
            }else if(BlastState.END_DEPLOYMENT.getCode().equals(blastDeployment.getState())){ //结束更新 撤销时间
                blastDeployment.setEndDeploymentTime(new Date());
            }else if(BlastState.START_DEPLOYMENT.getCode().equals(blastDeployment.getState())){ //调度确认 更新确认人 和 确认时间
                blastDeployment.setConfirmationPeopleId(SecurityUtils.getUserId()+"");
                SysUser data = remoteUserService.getUserById(SecurityUtils.getUserId()).getData();
                blastDeployment.setConfirmationPeople(data.getNickName());
                blastDeployment.setConfirmationTime(new Date());
            }else if(BlastState.START_BOMB.getCode().equals(blastDeployment.getState())){ //开始爆破 更新开始布防时间
                blastDeployment.setBeginDeploymentTime(new Date());
            }
        }

        blastDeployment.setUpdateTime(DateUtils.getNowDate());
        blastDeploymentMapper.deleteBlastDeploymentHoleSubtableByBlastDeploymentId(id);
        blastDeploymentMapper.deleteBlastDeploymentExplosiveSubtableByBlastDeploymentId(id);
        blastDeploymentMapper.deleteBlastDeploymentDetonatorSubtableByBlastDeploymentId(id);
        insertBlastDeploymentHoleSubtable(blastDeployment);
        return blastDeploymentMapper.updateBlastDeployment(blastDeployment);
    }

    /**
     * 批量删除爆破布防
     *
     * @param ids 需要删除的爆破布防主键
     * @return 结果
     */
    @Transactional
    @Override
    public int deleteBlastDeploymentByIds(String[] ids)
    {
        blastDeploymentMapper.deleteBlastDeploymentHoleSubtableByIds(ids);
        blastDeploymentMapper.deleteBlastDeploymentExplosiveSubtableByIds(ids);
        blastDeploymentMapper.deleteBlastDeploymentDetonatorSubtableByIds(ids);
        return blastDeploymentMapper.deleteBlastDeploymentByIds(ids);
    }

    /**
     * 删除爆破布防信息
     *
     * @param id 爆破布防主键
     * @return 结果
     */
    @Override
    public int deleteBlastDeploymentById(String id)
    {
        blastDeploymentMapper.deleteBlastDeploymentHoleSubtableByBlastDeploymentId(id);
        blastDeploymentMapper.deleteBlastDeploymentExplosiveSubtableByBlastDeploymentId(id);
        blastDeploymentMapper.deleteBlastDeploymentDetonatorSubtableByBlastDeploymentId(id);
        return blastDeploymentMapper.deleteBlastDeploymentById(id);
    }

    @Override
    public int deleteChargPositionByidByIds(String ids)
    {
        if(ids.indexOf(",")!=-1){
            String[] split = ids.split(",");
            String blastId = split[0];
            String holeId =split[1];
            BlastDeployment blastDeployment = blastDeploymentMapper.selectBlastDeploymentById(blastId);

            String chargePosition = blastDeployment.getChargePosition();
            if(StringUtils.isNotNull(chargePosition)){
                List<ChargePositionVo> cList = JSON.parseArray(chargePosition, ChargePositionVo.class);
                List<ChargePositionVo> collect = cList.stream().filter(v -> !v.getChargeHoleId().equals(holeId)).collect(Collectors.toList());
                BlastDeployment b= new BlastDeployment();
                if(StringUtils.isNotNull(collect)){
                    String s = JSONArray.parseArray(JSON.toJSONString(collect)).toString();
                    b.setId(blastId);
                    b.setChargePosition(s);
                }else {
                    b.setId(blastId);
                    b.setChargePosition("");
                }
                int i = blastDeploymentMapper.updateBlastDeployment(b);
                return i;
            }
        }
        return 0;
    }

    @Override
    public List<Map<String, Object>> getCameraIndexCodeType()
    {
        List<Map<String, Object>> maps = presetsPositionMapper.selectCameraIndexCodeType();
        return maps;
    }

    /**
     *
     * @return 返回自增编码
     */
    @Override
    public Map<String,String> getCode(){
        Map<String,String> map = new HashMap<>();
        SimpleDateFormat sd = new SimpleDateFormat("yyyyMMdd");
        String date = sd.format(new Date());
        String code= "";
        String prefix = "BP";
        // BP2022030401
        List<BlastDeployment> blastDeployments = blastDeploymentMapper.selectBlastDeploymentListAllByCode(null);
        if(blastDeployments!=null && blastDeployments.size()>0){
            BlastDeployment blastDeployment = blastDeployments.get(0);
            String localCode = blastDeployment.getCode();
            String pDate = localCode.substring(2,10);
            String pNumber = localCode.substring(localCode.length()-2);
            if(date.equals(pDate)){
                String next = getNext(pNumber);
                code = prefix+date+next;
                map.put("code",code);
                return map;
            }else {
                code = prefix+date+"01";
                map.put("code",code);
                return map;
            }
        }else{
            code = prefix+date+"01";
            map.put("code",code);
            return map;
        }
    }

    /**
     * 获取下一个编码序列
     * @param maxNumber  当前编码序列
     * @return
     */
    private static String getNext(String maxNumber) {
        int startValue = Integer.parseInt(maxNumber);
        AtomicInteger val = new AtomicInteger(startValue);
        int nextVal = val.incrementAndGet();
        return String.format("%02d", nextVal);
    }

    /**
     * 新增孔数信息子信息
     *
     * @param blastDeployment 爆破布防对象
     */
    public void insertBlastDeploymentHoleSubtable(BlastDeployment blastDeployment)
    {
        List<BlastDeploymentHoleSubtable> blastDeploymentHoleSubtableList = blastDeployment.getBlastDeploymentHoleSubtableList();
        List<BlastDeploymentExplosiveSubtable> blastDeploymentExplosiveSubtableList = blastDeployment.getBlastDeploymentExplosiveSubtableList();
        List<BlastDeploymentDetonatorSubtable> blastDeploymentDetonatorSubtableList = blastDeployment.getBlastDeploymentDetonatorSubtableList();
        String id = blastDeployment.getId();
        if (StringUtils.isNotNull(blastDeploymentHoleSubtableList))
        {
            List<BlastDeploymentHoleSubtable> list = new ArrayList<BlastDeploymentHoleSubtable>();
            for (BlastDeploymentHoleSubtable blastDeploymentHoleSubtable : blastDeploymentHoleSubtableList)
            {
                blastDeploymentHoleSubtable.setBlastDeploymentId(id);
                list.add(blastDeploymentHoleSubtable);
            }
            if (list.size() > 0)
            {
                blastDeploymentMapper.batchBlastDeploymentHoleSubtable(list);
            }
        }
        if (StringUtils.isNotNull(blastDeploymentExplosiveSubtableList))
        {
            List<BlastDeploymentExplosiveSubtable> list = new ArrayList<BlastDeploymentExplosiveSubtable>();
            for (BlastDeploymentExplosiveSubtable blastDeploymentExplosiveSubtable : blastDeploymentExplosiveSubtableList)
            {
                blastDeploymentExplosiveSubtable.setBlastDeploymentId(id);
                list.add(blastDeploymentExplosiveSubtable);
            }
            if (list.size() > 0)
            {
                blastDeploymentMapper.batchBlastDeploymentExplosiveSubtable(list);
            }
        }

        if (StringUtils.isNotNull(blastDeploymentDetonatorSubtableList))
        {
            List<BlastDeploymentDetonatorSubtable> list = new ArrayList<BlastDeploymentDetonatorSubtable>();
            for (BlastDeploymentDetonatorSubtable blastDeploymentDetonatorSubtable : blastDeploymentDetonatorSubtableList)
            {
                blastDeploymentDetonatorSubtable.setBlastDeploymentId(id);
                list.add(blastDeploymentDetonatorSubtable);
            }
            if (list.size() > 0)
            {
                blastDeploymentMapper.batchBlastDeploymentDetonatorSubtable(list);
            }
        }
    }
    //test
//    public static void main(String[] args)
//    {
//        GeometryFactory geometryFactory = JTSFactoryFinder.getGeometryFactory();
////        String position = "[{\"latitude\": \"45.480139\", \"longitude\": \"119.576092\", \"chargeHoleId\": \"ad53fb48487d425491a85c8b78ab3412\"}, {\"latitude\": \"45.480131\", \"longitude\": \"119.576091\", \"chargeHoleId\": \"f0e3627d8c124e648c0d9465396d424d\"}, {\"latitude\": \"45.480150\", \"longitude\": \"119.576070\", \"chargeHoleId\": \"fe72172945bb4453bd993d05e1fd798c\"}, {\"latitude\": \"45.480160\", \"longitude\": \"119.576010\", \"chargeHoleId\": \"43e63c79af0d4e158bb0ae17f45ae589\"}]";
//        String position = "[{\"latitude\": \"45.526263\", \"longitude\": \"119.652517\"}, {\"latitude\": \"45.526131\", \"longitude\": \"119.653377\"}, {\"latitude\": \"45.526163\", \"longitude\": \"119.652874\"}, {\"latitude\": \"45.526298\", \"longitude\": \"119.652952\"}, {\"latitude\": \"45.526666\", \"longitude\": \"119.652061\"}, {\"latitude\": \"45.526666\", \"longitude\": \"119.652061\"}]";
//        JSONArray pos = JSONArray.parseArray(position);
//        Coordinate[] c = new Coordinate[pos.size()];
//        for (int j = 0; j < pos.size(); j++)
//        {
//            JSONObject point = pos.getJSONObject(j);
//            double lon = point.getDouble("longitude");
//            double lat = point.getDouble("latitude");
//            c[j] = new Coordinate(lon, lat);
//        }
//        ConvexHull ch = new ConvexHull(c, geometryFactory);
//        Coordinate[] hull  = ch.getConvexHull().getCoordinates();
//        Polygon pplygon = geometryFactory.createPolygon(hull);
//        Point interiorPoint = pplygon.getInteriorPoint();
//        List<PresetsPosition> presets = new ArrayList<>();
//        PresetsPosition p = new PresetsPosition();
//        p.setId("74f9f408fe2e4304a7a82e546817daa8");
//        p.setPresetPointindex(HkConstant.HK_CAMERAINDEXCODE);
//        p.setLatitude("45.480139");
//        p.setLongitude("119.576092");
//        presets.add(p);
//        //获取和质心点最近的坐标
//        List<Pair<String, Double>> distList = new ArrayList<>();
//        for (int i = 0; i < presets.size(); i++)
//        {
//            PresetsPosition postion = presets.get(i);
//            Point point =geometryFactory.createPoint(new Coordinate(Double.valueOf(postion.getLongitude()),Double.valueOf(postion.getLatitude())));
//            Pair<String, Double> pair = new Pair(postion.getPresetPointindex(),interiorPoint.distance(point));
//            distList.add(pair);
//        }
//        Optional<Pair<String, Double>> minDist = distList.stream().sorted(Comparator.comparing(t ->t.getValue())).findFirst();
//        PresetVo presetVo = new PresetVo();
//        presetVo.setPresetIndex(minDist.get().getKey());
//
//    }

    /**
     * 筛选爆区布防的脏数据, 标准: 孔祥旭说判断下孔位是否在爆区里面
     */
    @Override
    public void filterDirtyData() {
        blastDeploymentDirtyMapper.delete(null);
        String mineScope = "[{\"longitude\":\"119.594174\",\"latitude\":\"45.453679\"},\n" +
                "{\"longitude\":\"119.607074\", \"latitude\":\"45.478440\"}, \n" +
                "{\"longitude\":\"119.610371\", \"latitude\":\"45.478382\"}, \n" +
                "{\"longitude\":\"119.616403\", \"latitude\":\"45.482770\"}, \n" +
                "{\"longitude\":\"119.607683\", \"latitude\":\"45.487019\"}, \n" +
                "{\"longitude\":\"119.618261\", \"latitude\":\"45.500060\"}, \n" +
                "{\"longitude\":\"119.617803\", \"latitude\":\"45.501796\"},\n" +
                "{\"longitude\":\"119.582003\", \"latitude\":\"45.520473\"}, \n" +
                "{\"longitude\":\"119.563157\", \"latitude\":\"45.513818\"}, \n" +
                "{\"longitude\":\"119.560511\", \"latitude\":\"45.498954\"}, \n" +
                "{\"longitude\":\"119.572788\", \"latitude\":\"45.482878\"}, \n" +
                "{\"longitude\":\"119.571973\", \"latitude\":\"45.477236\"},\n" +
                "{\"longitude\":\"119.566309\", \"latitude\":\"45.465388\"}, \n" +
                "{\"longitude\":\"119.570645\", \"latitude\":\"45.461327\"},\n" +
                "{\"longitude\":\"119.594174\", \"latitude\":\"45.453679\"}\n" +
                "]";
        Polygon polygons = getPolygons(mineScope);
        GeometryFactory geometryFactory = JTSFactoryFinder.getGeometryFactory();

        List<BlastDeployment> list = blastDeploymentMapper.selectBlastDeploymentList(new BlastDeployment());
        for(BlastDeployment blastDeployment : list) {
            String chargePosition = blastDeployment.getChargePosition();
            if(StringUtils.isNotEmpty(chargePosition)) {
                JSONObject obj = JSONArray.parseArray(chargePosition).getJSONObject(0);
                Point p = geometryFactory.createPoint(new Coordinate(obj.getDouble("longitude"), obj.getDouble("latitude")));
                if (! polygons.contains(p)) {
                    BlastDeploymentDirty blastDeploymentDirty = new BlastDeploymentDirty();
                    blastDeploymentDirty.setDirtyReason("孔位位置不在矿区内");
                    BeanUtils.copyBeanProp(blastDeploymentDirty, blastDeployment);
                    blastDeploymentDirtyMapper.insertBlastDeploymentDirty(blastDeploymentDirty);
                }
            } else {
                BlastDeploymentDirty blastDeploymentDirty = new BlastDeploymentDirty();
                blastDeploymentDirty.setDirtyReason("孔位信息为空");
                BeanUtils.copyBeanProp(blastDeploymentDirty, blastDeployment);
                blastDeploymentDirtyMapper.insertBlastDeploymentDirty(blastDeploymentDirty);
            }
        }

    }

    private Polygon getPolygons(String holeStr)
    {
        GeometryFactory geometryFactory = JTSFactoryFinder.getGeometryFactory();
        Polygon polygon = null;
        try
        {
            List<BpPoint> points = new ArrayList<>();
            JSONArray array = JSONArray.parseArray(holeStr);
            Coordinate[] c = new Coordinate[array.size()];
            for (int j = 0; j < array.size(); j++)
            {
                JSONObject point = array.getJSONObject(j);
                double lon = point.getDouble("longitude");
                double lat = point.getDouble("latitude");
                c[j] = new Coordinate(lon, lat);

            }
            //求解凸包
            ConvexHull ch = new ConvexHull(c, geometryFactory);
            Coordinate[] hull  = ch.getConvexHull().getCoordinates();
            polygon = geometryFactory.createPolygon(hull);
            //Point center = plygon.getInteriorPoint();
            //外扩多少米
            //Geometry waikuo =  getBufferedZipPolygon(plygon,0d);

            //获得外扩的米数
//            Coordinate[] waiPolygon = waikuo.getCoordinates();
//            points = Arrays.stream(waiPolygon).map(item -> new BpPoint(item.x, item.y)).collect(Collectors.toList());
//            polygonMap.setArea(points);
            //polygonMap.setLon(center.getX());
            //polygonMap.setLat(center.getY());

        } catch (Exception e) {
            e.printStackTrace();
        }
        return polygon;
    }
}
